package com.example.flow

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.fold
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.reduce
import kotlinx.coroutines.flow.single
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.flow.toSet
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.flow.zip
import kotlinx.coroutines.runBlocking
import org.junit.Test
import java.lang.ArithmeticException

class CoroutineTest03 {

    fun simpleFlow() = flow<Int> {
        for (i in 1..3) {
            println("emit=$i")
            emit(i)
        }
    }

    /**
     * 异常处理
     */
    @Test
    fun `test flow exception`() = runBlocking<Unit> {
        try {//捕获使用时异常 这种是命令式捕获
            simpleFlow().collect { value ->
                println("$value")
                check(value <= 1) {//符合条件的不会出现异常，否则抛出异常
                    "Collected $value"//异常信息
                }
            }
        } catch (e: Exception) {
            println("dddd----" + e.message)
        }
    }

    @Test
    fun `test flow exception2`() = runBlocking<Unit> {
        //声明式捕获
        flow {
            emit(1)
            throw ArithmeticException("Div 0")
        }.catch { e: Throwable ->
            println("打印：${e.message}")//捕获异常可以恢复
            emit(10)
        }.flowOn(Dispatchers.IO)
            .collect { println(it) }
    }

    fun simpleFlow2() = (1..3).asFlow()

    @Test
    fun `test flow complete finally`() = runBlocking<Unit> {
        try {
            simpleFlow2().collect { println(it) }
        } finally {
            //命令式
            println("Done")
        }
    }

    @Test
    fun `test flow complete in onCompletion`() = runBlocking<Unit> {
//        simpleFlow2().onCompletion {  println("Done") }.collect { println(it) }
//        simpleFlow3().onCompletion { println("Done---${it?.message}") }
//            .catch {
//                println("我捕获异常了")
//            }
//            .collect { println(it) }
//        onCompletion和catch不同之处就是它没有捕获异常，是拿到异常信息而已
        //上面的都是上游异常出问题
        //下面演示下游
            simpleFlow3().onCompletion { println("Done---${it?.message}") }
    //            .catch {
    //                println("我捕获异常了")
    //            }
                .collect { value ->
                    println(value)
                    check(value <= 1) {
                        "Collected $value"
                    }
                }
        //异常应该是从上到下的，一般不应该去在上游捕捉，应该继续到下游去处理

    }

    fun simpleFlow3() = flow<Int> {
        emit(11)
        throw ArithmeticException("错误了")
    }

}